[playid].vue 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. <script setup lang="ts">
  2. /* Import modules. */
  3. import { binToHex } from '@nexajs/utils'
  4. import { decodeAddress } from '@nexajs/address'
  5. import formatPosition from './_formatPosition.js'
  6. import moment from 'moment'
  7. import numeral from 'numeral'
  8. import { sha512 } from '@nexajs/crypto'
  9. const route = useRoute()
  10. const game = ref(null)
  11. const gameid = ref(null)
  12. const play = ref(null)
  13. const playid = ref(null)
  14. const entropy = ref(null)
  15. const title = ref(null)
  16. const summary = ref(null)
  17. const url = ref(null)
  18. const outcome = ref(null)
  19. const payout = ref(null)
  20. const playerJoy = ref(null)
  21. const position = ref(null)
  22. const rtp = ref(null)
  23. const satoshis = ref(null)
  24. const wagerNEX = ref(null)
  25. playid.value = route.params.playid
  26. console.log('PLAY ID', playid.value)
  27. const keyHash = computed(() => {
  28. if (entropy.value) {
  29. return sha512(sha512(entropy.value))
  30. } else {
  31. return null
  32. }
  33. })
  34. /**
  35. * Load Play
  36. */
  37. const loadPlay = async () => {
  38. play.value = await $fetch(`/api/plays/${playid.value}`)
  39. .catch(err => console.error(err))
  40. console.log('PLAY', play.value)
  41. if (typeof play.value === 'undefined') {
  42. const decoded = decodeAddress(playid.value)
  43. const hash = binToHex(decoded.hash)
  44. const pubKeyHash = hash.slice(8)
  45. play.value = await $fetch(`/api/plays/${pubKeyHash}`)
  46. .catch(err => console.error(err))
  47. console.log('(re-)PLAY', play.value)
  48. }
  49. gameid.value = play.value?.gameid
  50. entropy.value = play.value?.entropy
  51. payout.value = play.value?.payout + 'X'
  52. if (typeof play.value?.playerJoy !== 'undefined') {
  53. playerJoy.value = play.value.playerJoy
  54. }
  55. if (typeof play.value?.outcome !== 'undefined') {
  56. outcome.value = (play.value.outcome).toFixed(2)
  57. }
  58. if (typeof play.value?.satoshis !== 'undefined') {
  59. satoshis.value = play.value.satoshis
  60. wagerNEX.value = numeral(play.value.satoshis / 100.0).format('0,0.00')
  61. }
  62. rtp.value = play.value?.rtp + '%'
  63. /* Handle (player) position. */
  64. position.value = formatPosition(play.value?.position.toString())
  65. if (gameid.value) {
  66. /* Load game. */
  67. loadGame(gameid.value)
  68. }
  69. }
  70. /**
  71. * Load Game
  72. */
  73. const loadGame = async () => {
  74. game.value = await $fetch(`/api/games/${gameid.value}`)
  75. console.log('GAME', game.value)
  76. title.value = game.value?.title
  77. summary.value = game.value?.summary
  78. url.value = game.value?.url
  79. }
  80. loadPlay(playid)
  81. </script>
  82. <template>
  83. <main class="max-w-5xl mx-auto my-10 px-3">
  84. <section class="px-2 py-1 bg-yellow-200 border-2 border-yellow-400 rounded-lg shadow">
  85. <h3 class="text-xs text-yellow-700 font-medium uppercase">
  86. Fairplay Summary for Play ID
  87. </h3>
  88. <h2 class="text-sm text-yellow-900 font-bold font-mono tracking-wide truncate">
  89. {{playid}}
  90. </h2>
  91. </section>
  92. <h1 class="mt-5 mb-1 text-5xl font-medium">
  93. {{title || 'Anon'}}
  94. </h1>
  95. <NuxtLink :to="url" class="ml-2 text-blue-500 font-medium tracking-widest hover:underline">
  96. {{url || '...'}}
  97. </NuxtLink>
  98. <p class="my-5">
  99. {{summary || 'loading summary...'}}
  100. </p>
  101. <div class="flex flex-col gap-4">
  102. <FairplayItem
  103. v-if="playerJoy !== null"
  104. title="Player Joy"
  105. :value="playerJoy ? 'WIN' : 'LOSS'"
  106. />
  107. <FairplayItem
  108. v-if="outcome !== null"
  109. title="Play Outcome"
  110. :value="outcome || 'n/a'"
  111. />
  112. <FairplayItem
  113. v-if="wagerNEX !== null"
  114. title="Wager ( in NEXA )"
  115. :value="wagerNEX || 'n/a'"
  116. />
  117. <FairplayItem
  118. title="Player Payout"
  119. :value="payout || 'n/a'"
  120. />
  121. <FairplayItem
  122. title="Player Position"
  123. :value="position || 'n/a'"
  124. />
  125. <FairplayItem
  126. title="Average Return To Player ( RTP )"
  127. :value="rtp || 'n/a'"
  128. />
  129. <FairplayItem
  130. title="Play Created"
  131. :value="play?.createdAt ? moment(play.createdAt).fromNow() : 'loading...'"
  132. />
  133. <FairplayItem
  134. title="Play Completed"
  135. :value="play?.updatedAt ? moment(play.updatedAt).fromNow() : 'waiting for play...'"
  136. />
  137. <NuxtLink
  138. v-if="play?.txidem"
  139. :to="'https://explorer.nexa.org/tx/' + play.txidem" target="_blank"
  140. >
  141. <FairplayFeature
  142. title="Transaction Idem"
  143. :value="play.txidem || 'n/a'"
  144. />
  145. </NuxtLink>
  146. <hr class="my-5" />
  147. <FairplayItem
  148. title="Player ID / Wallet"
  149. :value="play?.playerid || 'n/a'"
  150. />
  151. <FairplayFeature
  152. title="Player Seed"
  153. :value="play?.seed"
  154. />
  155. <hr class="my-5" />
  156. <FairplayItem
  157. title="Gameplay Address"
  158. :value="play?.address || 'n/a'"
  159. />
  160. <FairplayItem
  161. title="Entropy"
  162. :value="entropy || 'n/a'"
  163. />
  164. <FairplayItem
  165. title="Mnemonic"
  166. :value="play?.mnemonic || 'n/a'"
  167. />
  168. <FairplayFeature
  169. title="Server Entropy (Private Key) Hash"
  170. :value="keyHash || 'n/a'"
  171. />
  172. </div>
  173. </main>
  174. </template>